
//
//  ReadingPickerViewController.m
//  Digital Seamonsters
//
//  Created by Adam Cue on 2/8/11.
//  Copyright Adam Cue 2011.
//
//  This program is licensed and distributed under the terms of the GNU General Public License.  
//	The text for the license can be found in the license.txt file in this project.
//

#import "ReadingPickerViewController.h"
#import "JSON.h"
#import "PDFViewController.h"
#import "PDFDocumentPreviewGridViewCell.h"

#define SHOW_CLASSES_BUTTON_FRAME      CGRectMake(-1, 254, 32, 192)
#define GRID_CELL_SIZE                 CGSizeMake(222, 317)
#define GRID_CELL_FRAME                CGRectMake(15, 0, 192, 317)

static dispatch_queue_t readingPickerQueue;

@interface ReadingPickerViewController (Private)
#pragma mark SetupMethods
- (void)setupGridView;
- (void)setupClassTable;
- (void)setupButtons;
- (void)setupNetworking;

#pragma mark UserActions
- (void)refresh;
- (void)oldClasses:(id)sender;

#pragma mark HelperMethods
- (void)checkNetworkStatus:(NSNotification *)notice;
- (void)loadReadings:(NSString *)jsonString;
- (void)loadSavedReadings;
- (void)doneShaking;
- (CAAnimation *)getShakeAnimation;
- (void)startLoading;
@end

@implementation ReadingPickerViewController

@synthesize readings = _readings;
@synthesize savedReadings = _savedReadings;
@synthesize savedReadingImages = _savedReadingImages;
@synthesize classTable = _classTable;
@synthesize showClassesButton = _showClassesButton;
@synthesize reach = _reach;
@synthesize gridView = _gridView;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
   if (self) {
      if(!readingPickerQueue) readingPickerQueue = dispatch_queue_create("com.Cachalot.ReadingPicker", NULL);
	   firstRun = YES;
	   internetAvailable = YES;
	   firstLoad = YES;
      _savedReadings = [[NSMutableArray alloc] initWithCapacity:2];
      _savedReadingImages = [[NSMutableArray alloc] initWithCapacity:2];
   }
   return self;
}

- (void)viewDidLoad {
   [super viewDidLoad];
   self.view.backgroundColor = [UIColor blackColor];
   UIImageView * backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"grid_background"]] autorelease];
   backgroundView.alpha = 0.3;
   [self.view addSubview:backgroundView];
   
   [self setupGridView];
   [self setupClassTable];
   [self setupButtons];
   [self setupNetworking];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   // Overriden to allow any orientation.
   return interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}

- (void)viewDidUnload {
   [super viewDidUnload];
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   self.reach = nil;
}


- (void)dealloc {
	self.readings = nil;
   self.savedReadings = nil;
   self.savedReadingImages = nil;
   self.showClassesButton = nil;
   self.classTable = nil;
   self.reach = nil;
   self.gridView = nil;
   
	[super dealloc];
}

#pragma mark SetupMethods
- (void)setupGridView {
   _gridView = [[AQGridView alloc] initWithFrame:CGRectMake(0, 0, 1024, 660)];
   self.gridView.backgroundColor = [UIColor clearColor];
   self.gridView.opaque = NO;
   self.gridView.dataSource = self;
   self.gridView.delegate = self;
   UIView *clearView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)] autorelease];
   clearView.backgroundColor = [UIColor clearColor];
   self.gridView.gridHeaderView = clearView;
   self.gridView.leftContentInset = 15.0;
   self.gridView.rightContentInset = 15.0;
   [self.view addSubview:self.gridView]; 
}

- (void)setupClassTable {
   _classTable = [[ClassReadingsTableViewController alloc] initWithStyle:UITableViewStylePlain];
   self.classTable.delegate = self;
   self.classTable.tableView.frame = CGRectMake(-320, 0, 320, 704);
   self.classTable.tableView.separatorColor = [UIColor darkGrayColor];
   self.classTable.tableView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.84];
   self.classTable.tableView.hidden = YES;
   [self.view addSubview:self.classTable.tableView];
}

- (void)setupButtons {
   _showClassesButton = [UIButton buttonWithType:UIButtonTypeCustom];
   self.showClassesButton.frame = SHOW_CLASSES_BUTTON_FRAME;
   [self.showClassesButton setImage:[UIImage imageNamed:@"classes_pullout"] forState:UIControlStateNormal];
   [self.showClassesButton addTarget:self action:@selector(oldClasses:) forControlEvents:UIControlEventTouchUpInside];
   [self.view addSubview:self.showClassesButton];
   UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refresh)];
   self.navigationItem.rightBarButtonItem = refreshButton;
   [refreshButton release];
}

- (void)setupNetworking {
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
   self.reach = [Reachability reachabilityWithHostName:@"seamonster.ml.duke.edu"];
   [self.reach startNotifier];
}

#pragma mark UserActions
- (void)refresh{
   if(internetAvailable == NO){
	   UIAlertView *noInternetAlert = [[[UIAlertView alloc] initWithTitle:@"Connection required!" message:@"Could not download latest class' readings.  Check back when you have an internet connection." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
	   [noInternetAlert show];
	   return;
   }
   [DSBezelActivityView newActivityViewForView:self.view withLabel:@"Loading Readings"];
   [self loadReadings:nil];
}

- (void)oldClasses:(id)sender{
  if(firstRun){
    self.classTable.tableView.frame = CGRectMake(-320, 0, 320, 704);
  }
  firstRun = NO;
  [UIView animateWithDuration:0.8 delay:0.0 options:UIViewAnimationCurveLinear 
                   animations:^{
                     self.classTable.tableView.hidden = NO;
                     if(self.classTable.tableView.left < 0){
                       self.showClassesButton.left = 319;
                       self.classTable.tableView.left = 0;
                       [self.showClassesButton setImage:[UIImage imageNamed:@"Hide_Pullout"] forState:UIControlStateNormal];
                     }
                     else{
                       self.showClassesButton.left = -1;
                       self.classTable.tableView.right = 0;
                       [self.showClassesButton setImage:[UIImage imageNamed:@"classes_pullout"] forState:UIControlStateNormal];
                     }
                   }completion:nil];
}

#pragma mark HelperMethods
- (void)checkNetworkStatus:(NSNotification *)notice{
   NetworkStatus internetStatus = [self.reach currentReachabilityStatus];
   switch (internetStatus){
	   case NotReachable:{
		   internetAvailable = NO;
		   break;
	   }
	   case ReachableViaWiFi:{
		   internetAvailable = YES;
         dispatch_async(readingPickerQueue, ^{[self.classTable loadClassList];});
		   break;
	   }
	   case ReachableViaWWAN:{
		   internetAvailable = YES;
         dispatch_async(readingPickerQueue, ^{[self.classTable loadClassList];});
		   break;
		   
	   }
   }
   if(firstLoad == YES){
      [DSBezelActivityView newActivityViewForView:self.view withLabel:@"Loading Readings"];
	   dispatch_async(readingPickerQueue, ^{[self loadReadings:nil];});
   }
   firstLoad = NO;
}

- (void)loadReadings:(NSString *)jsonString{
   if(internetAvailable == NO){
      dispatch_async(dispatch_get_main_queue(), ^{
         self.title = @"Readings";
         UIAlertView *noInternetAlert = [[[UIAlertView alloc] initWithTitle:@"Connection required!" message:@"Could not download latest class' readings.  Check back when you have an internet connection." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
         [noInternetAlert show];
      });
      return;
   }
   internetAvailable = YES;
   if(jsonString == nil){
      jsonString = [[[NSString alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:NEW_READINGS_URL]] encoding:NSUTF8StringEncoding] autorelease];
   }
   if(self.classTable.listOfClasses){
      [self.classTable loadClassList];
   }
   NSDictionary *classInfo = [jsonString JSONValue];
   self.readings = [classInfo objectForKey:@"readings"];
   NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
   [dateFormatter setDateFormat:@"yyyy-MM-dd"];
   NSDate *date = [dateFormatter dateFromString:[classInfo objectForKey:@"date"]];
   [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
   dispatch_async(dispatch_get_main_queue(), ^{
      self.title = [NSString stringWithFormat:@"%@ - %@", [classInfo objectForKey:@"name"], [dateFormatter stringFromDate:date]];
      self.navigationController.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Readings" image:[UIImage imageNamed:@"readings_tab"] tag:0] autorelease];
      [DSBezelActivityView removeViewAnimated:YES];
      [self.gridView reloadData];
   });
   [dateFormatter release];
}

- (void)loadSavedReadings{
   NSFetchRequest *readingRequest = [[NSFetchRequest alloc] init];
	NSEntityDescription *readingEntity = [NSEntityDescription entityForName:@"Reading" inManagedObjectContext:[[MarineFetcher sharedInstance] managedObjectContext]];
	[readingRequest setEntity:readingEntity];
	[readingRequest setPredicate:[NSPredicate predicateWithFormat:@"isRecent == %@", [NSNumber numberWithBool:NO]]];
	NSError *readingError;
	NSArray *readingFetchResults = [[[MarineFetcher sharedInstance] managedObjectContext] executeFetchRequest:readingRequest error:&readingError];
	if (readingFetchResults == nil) {
		NSLog(@"%@", readingError);
	}
	self.savedReadings = [readingFetchResults mutableCopy];
   [self.savedReadings release];
	dispatch_async(dispatch_get_main_queue(), ^{
      self.title = @"Saved Readings";
      self.navigationController.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Readings" image:[UIImage imageNamed:@"readings_tab"] tag:0] autorelease];
      [DSBezelActivityView removeViewAnimated:YES];
      [self.gridView reloadData];
   });
}

- (void)doneShaking{
	self.navigationItem.leftBarButtonItem = nil;
	for(UIView *cellView in self.savedReadingImages){
		[cellView layer].transform = CATransform3DMakeRotation(0, 0, 0, 1.0);
		[[cellView layer] removeAllAnimations];
	}
   [self.savedReadingImages removeAllObjects];
   for(int i = 0; i < [self.savedReadings count]; i++){
      PDFDocumentPreviewGridViewCell * cell = (PDFDocumentPreviewGridViewCell *)[self gridView:self.gridView cellForItemAtIndex:i];
      [cell.asyncDocumentPreviewView doneShaking];
   }
	[self.gridView reloadData];
}

- (CAAnimation *)getShakeAnimation {
    CABasicAnimation *animation;
    CATransform3D transform;
    // Create the rotation matrix
    transform = CATransform3DMakeRotation(0.01, 0, 0, 1.0);
    // Create a basic animation to animate the layer's transform
    animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    // Assign the transform as the animation's value
    animation.toValue = [NSValue valueWithCATransform3D:transform];
    animation.autoreverses = YES;  
    animation.duration = 0.1;  
    animation.repeatCount = HUGE_VALF;  
    return animation;	
}

- (void)startLoading{
  [DSBezelActivityView newActivityViewForView:self.view withLabel:@"Loading Readings..." width:160];
  [UIView animateWithDuration:0.8 delay:0.0 options:UIViewAnimationCurveLinear 
                   animations:^{
                     self.showClassesButton.left = -1;
                     self.classTable.tableView.right = 0;
                     [self.showClassesButton setImage:[UIImage imageNamed:@"classes_pullout"] forState:UIControlStateNormal];
                   } completion:nil];
}

#pragma mark ClassReadingsTableViewControllerDelegate
- (void)classClicked:(int)classID{
   if(classID == -1){
	   saveReadings = YES;
	   [self startLoading];
      dispatch_async(readingPickerQueue, ^{[self loadSavedReadings];});
   }
   else{
	   saveReadings = NO;
	   [self startLoading];
	   NSString *jsonString = [[[NSString alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:PARTICULAR_READINGS_URL, classID]]] encoding:NSUTF8StringEncoding] autorelease];
	   dispatch_async(readingPickerQueue, ^{[self loadReadings:jsonString];});
   }
}

#pragma mark AQGridView Data Source
- (NSUInteger) numberOfItemsInGridView: (AQGridView *) gridView{
	if(saveReadings){
		return [self.savedReadings count];
	}
	return [self.readings count];
}

- (AQGridViewCell *) gridView: (AQGridView *) gridView cellForItemAtIndex: (NSUInteger) index
{
	static NSString * ReadingCellIdentifier = @"ReadingCellIdentifier";
	PDFDocumentPreviewGridViewCell *cell = (PDFDocumentPreviewGridViewCell *)[self.gridView dequeueReusableCellWithIdentifier:ReadingCellIdentifier];
	if(cell == nil) cell = [[[PDFDocumentPreviewGridViewCell alloc] initWithFrame:GRID_CELL_FRAME reuseIdentifier:ReadingCellIdentifier] autorelease];
	cell.superViewController = self;
   if(saveReadings == YES){
      Reading *reading = [self.savedReadings objectAtIndex:index];
		[PDFDocumentPreviewGridViewCell fillCell:cell forSavedReading:reading atIndex:index];
		[self.savedReadingImages addObject:cell.contentView];
		return cell;
	}
   else{
      [PDFDocumentPreviewGridViewCell fillCell:cell forReading:[self.readings objectAtIndex:index] atIndex:index];
      return cell;
   }
}

- (CGSize) portraitGridCellSizeForGridView: (AQGridView *) gridView{
  return GRID_CELL_SIZE;
}

#pragma mark AQGridView Delegate
- (void) gridView: (AQGridView *) gridView didSelectItemAtIndex: (NSUInteger) index{}

#pragma mark PDFDocumentPreviewViewDelegate
- (void)deleted:(int)index{
	Reading *reading = [self.savedReadings objectAtIndex:index];
	[[[MarineFetcher sharedInstance] managedObjectContext] deleteObject:reading];
	NSError *saveError;
	[[[MarineFetcher sharedInstance] managedObjectContext] save:&saveError];
   [self.savedReadings removeObjectAtIndex:index];
   [self.gridView deleteItemsAtIndices:[[[NSIndexSet alloc] initWithIndex:index] autorelease] withAnimation:AQGridViewItemAnimationLeft];
	[self doneShaking];
}

- (void)selected:(int)index withImage:(UIImage *)selectedImage{
	if(saveReadings == YES){
		PDFViewController *pdfVC = [[PDFViewController alloc] initWithNibName:@"PDFViewController" bundle:[NSBundle mainBundle] savedReading:[self.savedReadings objectAtIndex:index]];
		pdfVC.title = [[self.savedReadings objectAtIndex:index] name];
		pdfVC.readingID = [[[self.savedReadings objectAtIndex:index] readingID] intValue];
		[self.navigationController pushViewController:pdfVC animated:YES];
		[pdfVC release];
		return;
	}
	PDFViewController *pdfVC = [[PDFViewController alloc] initWithNibName:@"PDFViewController" bundle:[NSBundle mainBundle] fileURL:[[self.readings objectAtIndex:index] objectForKey:@"path"] name:[[self.readings objectAtIndex:index] objectForKey:@"name"] thumb:selectedImage];
	pdfVC.title = [[self.readings objectAtIndex:index] objectForKey:@"name"];
	pdfVC.readingID = [[[self.readings objectAtIndex:index] objectForKey:@"id"] intValue];
	[self.navigationController pushViewController:pdfVC animated:YES];
	[pdfVC release];
}

- (void)shaking{
   for(UIView *cellView in self.savedReadingImages){
      [((PDFDocumentPreviewView *) ([cellView.subviews objectAtIndex:1])) showCloseButton];
      [cellView layer].transform = CATransform3DMakeRotation(-.01, 0, 0, 1.0);
      [[cellView layer] addAnimation:[self getShakeAnimation] forKey:@"shake"];
   }
   self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneShaking)] autorelease];
}

@end
